<script setup lang="ts" >
  import { onMounted, reactive, ref, watch } from 'vue'
  import { ElMessageBox, UploadProps } from 'element-plus';
  import { ToastWarning } from '@/utils/public';
  import { Plus } from '@element-plus/icons-vue'
  import { oss_url } from '@/pinia/getter'
  const $emit = defineEmits(['update:fileList', 'success', 'update:fileUrl', 'update:fileMd5'])
  const dialogImageUrl = ref('')
  const dialogVisible = ref(false)
  const baseURL = import.meta.env.VITE_HTTP;
  const action = reactive({
    dialog:false,
    uploadLoading:false,
    emitlist:[] as any[],
    fileName:'',
    fileNum:0,
    fileList:[] as Array<fileForm>
  })
  const props = defineProps({
    butText:{
      type:String,
      default:'点击上传'
    },
    /**
     * 是否支持多选
     */
    multiple:{
      type:Boolean,
      default:false
    },
    /**
     * 携带参数
     */
    data:{
      type:Object,
      default:{}
    },
    // 最大上传数
    limit:{
      type:Number,
      default:1,
    },
    /**
     * 上传地址
     */
    uploadUrl:{
      type:String,
      default:'/api/file/upload'
    },
    /**
     * 文件列表
     */
    fileList:{
      type:Array<string>,
      default:()=>[] as Array<string>
    },
    /**
     * 单文件
     */
    fileUrl:{
      type:String,
      default:''
    },
    /**
     * listType:'text' | 'picture' | 'picture-card'
     */
    listType:{
      type:String,
      default:'picture-card'
    },
    /**
     * 是否显示上传的文件列表
     */
    showFileList:{
      type:Boolean,
      default:true,
    }
  })
  interface fileForm {
    name:string
    url:string
  }
  
  const filtersFile = (url:string = '')=>{
    if( props.listType == 'text' ) return url
    if(url.indexOf(oss_url.value) > -1) {
      return url
    }
    return `${oss_url.value}/${url}`
  }
  const filtersFileName = (url:string = '')=>{
    return action.emitlist.find(res=> res.url == url)?.name || url
  }
  watch(props,()=>{
    if(props.fileList.length > 1) return
    getFileList()
  })
  const getFileList = ()=>{
    let list = [] as Array<fileForm>
    if(props.fileList.length == 0 && props.fileUrl == '') {
      action.fileNum = 0
      action.fileName = ''
      action.fileList = []
      action.emitlist = []
      return
    }
    if(props.limit == 1 && props.fileUrl) {
      list = [{
        name:filtersFileName(props.fileUrl),
        url:filtersFile(props.fileUrl)
      }]
    } else if (props.fileList.length > 0) {
      list = props.fileList.map(res=>{
        return {
          name:filtersFileName(res),
          url:filtersFile(res)
        }
      })
    }
    action.fileList = list
    action.emitlist = list
  }
  // 上传前钩子
  const beforeUpload = (file: { name: string; }) => {
    action.fileNum += 1
    action.fileName = file.name
    action.uploadLoading = true
  }
  /**
   * 上传成功钩子
   * @param res 
   */
  const successChange = (res: { data: { uri: any; md5:any }; })=> {
    action.fileNum -= 1
    let { uri='', md5='' } = res.data
    action.emitlist.push({
      name:action.fileName,
      url:'/'+uri,
      md5
    })
    emitValue()
    action.uploadLoading = false
  }
  // 上传失败回调
  const errorChange = () => {
    action.fileNum -= 1
    action.uploadLoading = false
    ToastWarning(`${action.fileName}文件上传失败`)
  }
  // 删除列表中的图片之前
  const beforeRemove: UploadProps['beforeRemove'] = (uploadFile, uploadFiles) => {
    return ElMessageBox.confirm(
      `是否删除 ${uploadFile.name || ''} ?`,"提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }
    ).then(
      () => true,
      () => false
    )
  }
  // 已删除列表图片
  const handleRemove = (file: any, fileList: any[]) => {
    action.emitlist = fileList.map((row: { name: any; response: { data: { uri: any; }; }; })=>{
      return {
        name:row.name,
        url:row.response.data.uri
      }
    })
    emitValue()
  }
  const handleExceed = (file: any,fileList: any) => {
    ToastWarning(`当前限制选择 ${props.limit} 个文件`)
  }
  const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
    dialogImageUrl.value = uploadFile.url!
    dialogVisible.value = true
  }
  // const addhttp = (url)=> {
  //   return oss_url + url
  // },
  const deloss_url = (url:string)=>{
    return url.indexOf(oss_url.value) > -1 ? url.replace(oss_url.value + '/','') : url 
  }
  const emitValue = ()=> {
    if(action.fileNum > 0) return
    let data = [] as Array<any>;
    let fileUrl = ''
    let md5Url = ''
    if(action.emitlist.length == 0) {
      if(props.limit == 1) {
        fileUrl = ''
        md5Url = ''
      }
    }else {
      if(props.limit == 1) {
        fileUrl = action.emitlist[0].url
        md5Url = action.emitlist[0].md5
      }else {
        data = action.emitlist.map(res=>{
          return deloss_url(res.url)
        })
      }
    }
    if(props.limit == 1) {
      $emit('update:fileUrl',fileUrl)
      $emit('update:fileMd5',md5Url)
    } else {
      $emit('update:fileList',data)
    }
    $emit('success',data)
  }
  onMounted(()=>{
    getFileList()
  })
</script>
<template>
  <div class="el-upload-box">
    <el-upload
      :class="props.limit == action.fileList.length && props.limit > 0 ?'uploadClass' :''"
      :action="baseURL + uploadUrl"
      :on-remove="handleRemove"
      :before-remove="beforeRemove"
      :on-error="errorChange"
      :before-upload="beforeUpload"
      :on-success="successChange"
      :on-preview="handlePictureCardPreview"
      :list-type="listType"
      :on-exceed="handleExceed"
      :show-file-list="showFileList"
      :multiple="props.multiple"
      :data="data"
      :limit="limit"
      v-model:file-list="action.fileList">
      <el-button :loading="action.uploadLoading" v-if="listType != 'picture-card'" type="primary">{{action.uploadLoading?'正在上传':props.butText}}</el-button>
      <el-icon v-if="listType == 'picture-card'" ><Plus /></el-icon>
    </el-upload>
    <el-dialog class="img-dialog" top="0vh" v-model="dialogVisible">
      <img class="image" :src="dialogImageUrl"/>
    </el-dialog>
  </div>
</template>

<script>
</script>
<style lang='scss' scoped>
  .el-upload-box {
    max-width: 100%;
  }
  :deep(.uploadClass) {
    .el-upload {
      display: none;
    }
    .el-upload-list {
      margin: 0;
    }
  }
  :deep(.img-dialog) {
    --el-bg-color:none;
    .el-dialog__header {
      display: none;
    }
    .el-dialog__body {
      padding: 0;
      height: max-content !important;
    }
  }
  .image {
    width: 100%;
    height: auto;
  }
</style>